package iface.aplicativo.apresentacao.controle;

import iface.aplicativo.excecao.MensagemException;
import iface.aplicativo.negocio.aps.ManterPerfisAPS;
import iface.aplicativo.negocio.entidade.Menu;
import iface.aplicativo.negocio.entidade.Perfil;
import iface.aplicativo.util.BeanAbstrato;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;

import org.primefaces.model.TreeNode;

@ManagedBean
@SessionScoped
public class ManterPerfisBean extends BeanAbstrato implements Serializable {

	private static final long serialVersionUID = 4285899560377776076L;

	private Perfil perfil;
	private Perfil perfilAux;

	private TreeNode root;
	private TreeNode[] selectedNodes;

	@ManagedProperty(value = "#{manterPerfisAPS}")
	private ManterPerfisAPS service;

	public void setService(ManterPerfisAPS service) {
		this.service = service;
	}

	public Collection<Perfil> getTodosPerfis() throws Exception {
		return this.service.getTodosPerfis();
	}

	public String salvarPerfil() throws Exception {

		try {
			String msg = this.service.salvarPerfil(this.getPerfil(),
					this.getSelectedNodes());
			this.limparCampos();

			this.setMensagem(msg, MSG_TIPO_INFORMACAO, "");
		} catch (final MensagemException e) {
			this.setMensagem(e.getMessage(), MSG_TIPO_AVISO, "");
		} catch (final Exception e) {
			this.setMensagem(e.getMessage(), MSG_TIPO_ERRO, "");
		}

		return "inicial";
	}

	public void excluirPerfil() throws Exception {

		try {
			String msg = this.service.excluirPerfil(this.getPerfilAux());

			this.limparCampos();

			this.setMensagem(msg, MSG_TIPO_INFORMACAO, "");
		} catch (final MensagemException e) {
			this.setMensagem(e.getMessage(), MSG_TIPO_AVISO, "");
		} catch (final Exception e) {
			this.setMensagem(e.getMessage(), MSG_TIPO_ERRO, "");
		}
	}

	public void limparCampos() {
		this.setPerfil(null);
		this.setPerfilAux(null);
		this.setRoot(null);
	}

	public Perfil getPerfil() {
		if (perfil == null) {
			perfil = new Perfil();
		}
		return perfil;
	}

	public void setPerfil(Perfil perfil) {
		this.perfil = perfil;
	}

	public Perfil getPerfilAux() {
		if (perfilAux == null) {
			perfilAux = new Perfil();
		}
		return perfilAux;
	}

	public void setPerfilAux(Perfil perfilAux) {
		this.perfilAux = perfilAux;
	}

	public TreeNode[] getSelectedNodes() {
		return selectedNodes;
	}

	public void setSelectedNodes(TreeNode[] selectedNodes) {
		this.selectedNodes = selectedNodes;
	}

	public TreeNode getRoot() {
		if (root == null || root.getChildren() == null
				|| root.getChildren().isEmpty()) {
			root = this.service.construirTreeMenus();
		}

		if (this.getPerfil() != null && this.getPerfil().getMenus() != null
				&& !this.getPerfil().getMenus().isEmpty()) {
			this.marcarItensSelecionados(root.getChildren());
		}

		return root;
	}

	public TreeNode getRootDetalhes() {
		if (this.getPerfilAux().getIdentificador() != null) {
			return this.service.construirDetalhesTreeMenus(this.getPerfilAux());
		}
		return null;
	}

	public boolean marcarItensSelecionados(List<TreeNode> filhos) {
		boolean filhoMarcado = false;
		for (TreeNode filho : filhos) {
			if (filho.getChildCount() > 0) {
				filhoMarcado = this
						.marcarItensSelecionados(filho.getChildren());
			}

			if ((((Menu) filho.getData()).getMenuPai() == null && !filhoMarcado && this
					.getPerfil().getMenus().contains((Menu) filho.getData()))
					|| (((Menu) filho.getData()).getMenuPai() != null && this
							.getPerfil().getMenus()
							.contains((Menu) filho.getData()))
					|| (((Menu) filho.getData()).getMenuPai() == null
							&& ((Menu) filho.getData()).getFilhos().isEmpty() && this
							.getPerfil().getMenus()
							.contains((Menu) filho.getData()))) {
				filho.setSelected(true);
				filho.setExpanded(true);
				if (((Menu) filho.getData()).getMenuPai() != null) {
					filhoMarcado = true;
				}
			}
		}
		return filhoMarcado;
	}

	public void setRoot(TreeNode root) {
		this.root = root;
	}

}
